package com.liu.network.httpclient;

import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpVersion;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.params.CoreConnectionPNames;
import org.apache.http.params.CoreProtocolPNames;

public class HtmlTool {
	public static void main(String[] args) {
		// String str =
		// getHttpsHtmlFilterScript("https://192.168.100.1/login#/login");
		String str = getHttpsHtmlFilterScript("https://47.97.196.98:8834/session");
		// String str = getHttpsHtmlFilterScript("https://220.181.38.148");
		try {
			FileWriter out = new FileWriter(new File("C:/Users/ydxx/Desktop/1.html"));
			out.write(str);
			out.flush();
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public static String getHttpsHtmlFilterScript(String URL) {
		CloseableHttpResponse response = null;
		String body = "<html><head><link href='/web/css/pm/httpViewNew.css' rel='stylesheet' type='text/css'/><script>window.parent.document.getElementById('screenshotIframe').style.backgroundColor='rgba(0,0,0,0)';</script></head><body><div style='text-align:center;'><img src='/web/img/pm/http_loaderror.png' class='loadErrorImg' /><span class='loadErrorDesc'>数据无法显示，请稍后再试！</span></div></body></html>";
		BufferedInputStream in = null;
		ByteArrayOutputStream out = null;
		StringBuffer sb = new StringBuffer();
		// 采用绕过验证的方式处理https请求
		SSLContext sslcontext = createIgnoreVerifySSL();

		// SSLContext sslcontext = SSLContext.getInstance("TLS");
		// sslcontext.init(null, null, null);
		// SSLSocketFactory sf = new
		// SSLSocketFactory(sslcontext,SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
		// Scheme sch = new Scheme("https", 443, sf);
		// sf.getHttpClient().getConnectionManager().getSchemeRegistry().register(sch);
		// HttpGet httpGet = new HttpGet(URL);
		// 设置协议http和https对应的处理socket链接工厂的对象
		Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
				.register("http", PlainConnectionSocketFactory.INSTANCE)
				.register("https", new SSLConnectionSocketFactory(sslcontext)).build();
		PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
		HttpClients.custom().setConnectionManager(connManager);

		// 创建自定义的httpclient对象
		CloseableHttpClient client = HttpClients.custom().setConnectionManager(connManager).build();

		// 创建post方式请求对象
		// HttpPost httpPost = new HttpPost(URL);
		HttpGet httpPost = new HttpGet(URL);
		try {
			// 设置header信息
			// 指定报文头【Content-type】、【User-Agent】
			httpPost.setHeader("Content-type", "application/x-www-form-urlencoded");
			httpPost.setHeader("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");

			response = client.execute(httpPost);// 执行请求操作，并拿到结果（同步阻塞）
			HttpEntity entity = response.getEntity(); // 获取结果实体

			String encode = null;
			if (entity != null) {
				Header header = entity.getContentType();// 读取实体头部信息Content-Type;
				if (header != null) {
					encode = header.getValue();// 获取头部信息meta的value;例如 text/html;
												// charset=utf-8
					int index = encode.indexOf("charset=");
					encode = index == -1 ? null : encode.substring(index + 8);// 截取编码方式
				}

				in = new BufferedInputStream(entity.getContent());// 从实体中读取内容写入
				out = new ByteArrayOutputStream();
				byte[] temp = new byte[2048];
				int size = 0;
				while ((size = in.read(temp)) != -1) {
					out.write(temp, 0, size);
				}
				byte[] content = out.toByteArray(); // 得到实体的内容
				if (encode == null) {// 如果获取头部信息的编码方式失败，那就设置默认为utf-8
					String html_utf8 = new String(content, "utf-8");
					Pattern p = Pattern.compile("(?i)<meta.+?charset=[\"\']?(.*?)[\"\'][^/]*?/?>"); // (?i)不区分大小写
																									// [^/]除/之外的字符
					Matcher m = p.matcher(html_utf8);
					while (m.find()) {
						encode = m.group(1);// 得到匹配到的<meta>之前的所有信息
						break;
					}
				}
				String str = new String(content, encode == null ? "utf-8" : encode);// 设置实体的编码
				String uri = URL.substring(0, URL.indexOf("/", 8) + 1);// 得到http://xxxxxxxx/或者https://xxxxxxx/形式的url
				if (URL.equalsIgnoreCase("http://www.baidu.com/")
						|| URL.matches("http://www.baidu.com/index.(php|html|htm)(\\?.*)?")
						|| str.matches("(?i).*?</head>\\s*<body>\\s*</body>\\s*</html>\\s*")) {
					sb.append(body); // body内为空时显示默认提示
				} else {
					// 去掉script(去掉js);把src路径全部换成之前得到的uri;去掉meta中的http-equiv与content防止服务器将把名称/值对添加到发送给浏览器的内容头部
					sb.append(str.replaceAll("(?i)<(\\\\?/?)script([\\s\\S]*?)>", "<$1noscript$2>")// script变为noscript
							.replaceAll("(?i)src=([\"\'])/", "src=$1" + uri)// script的uri变成绝对地址
							.replaceAll("(?i)(<link.*?)rel=stylesheet", "$1 rel=\"stylesheet\"")// link的rel=stylesheet变成rel="stylesheet"
							.replaceAll("(?i)(<link.*?)(href=[\"\'](\\.\\.\\/|\\/){0,2}.*?)rel=\"stylesheet\"",
									"$1 rel=\"stylesheet\" $2")// link的rel="stylesheet"统一放在href之前
							.replaceAll("(?i)(<link.*?)(rel=\"stylesheet\").*?href=[\"\'](\\/\\/)",
									"$1 rel=\"stylesheet\" href=\"https://")// link的href以//开头的链接地址加上https:
							.replaceAll("(?i)(<link.*?)(rel=\"stylesheet\").*?href=[\"\'](\\.\\.\\/|\\/){0,2}(?!http)",
									"$1 rel=\"stylesheet\" href=\"" + uri)// link的href变成绝对地址
							.replaceAll("(?i)(<img.*?)src=[\"\'](\\/\\/)", "$1 src=\"https://")// img的src以//开头的链接地址加上https:
							.replaceAll("(?i)(<img.*?)src=[\"\'](\\.\\.\\/|\\/){0,2}(?!http)", "$1src=" + '"' + uri)// img的src变成绝对地址
							.replaceAll(
									"(?i)(<meta.+?http-equiv=[\"\']refresh[\"\'].*?content=[\"\'].*?url=)/?(.*?[\"\'][^/]*?/?>)",
									""));
				}
			}
			// EntityUtils.consume(entity);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			try {
				response.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		String result = sb.toString();
		if (result.length() == 0)
			result = body;
		return result;
	}

	private static SSLContext createIgnoreVerifySSL() {
		SSLContext sc = null;
		try {
			sc = SSLContext.getInstance("TLS");

			// 实现一个X509TrustManager接口，用于绕过验证，不用修改里面的方法
			X509TrustManager trustManager = new X509TrustManager() {
				public void checkClientTrusted(java.security.cert.X509Certificate[] paramArrayOfX509Certificate,
						String paramString) {
				}

				public void checkServerTrusted(java.security.cert.X509Certificate[] paramArrayOfX509Certificate,
						String paramString) {
				}

				public java.security.cert.X509Certificate[] getAcceptedIssuers() {
					return null;
				}
			};
			sc.init(null, new TrustManager[] { trustManager }, null);
		} catch (KeyManagementException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (NoSuchAlgorithmException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return sc;
	}

	public static String getHtmlFilterScript(String URL) {
		String defaultResult = "<html><head><link href='/web/css/pm/httpViewNew.css' rel='stylesheet' type='text/css'/><script>window.parent.document.getElementById('screenshotIframe').style.backgroundColor='rgba(0,0,0,0)';</script></head><body><div style='text-align:center;'><img src='/web/img/pm/http_loaderror.png' class='loadErrorImg' /><span class='loadErrorDesc'>数据无法显示，请稍后再试！</span></div></body></html>";
		HttpClient httpclient = null;
		BufferedInputStream in = null;
		ByteArrayOutputStream out = null;
		StringBuffer sb = new StringBuffer();
		try {
			httpclient = new DefaultHttpClient();

			httpclient.getParams().setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1);
			httpclient.getParams().setParameter(CoreProtocolPNames.USER_AGENT,
					"Mozilla/5.0 (X11; U; Linux i686; zh-CN; rv:1.9.1.2) Gecko/20090803 Fedora/3.5.2-2.fc11 Firefox/3.5.2");
			httpclient.getParams().setParameter(CoreProtocolPNames.USE_EXPECT_CONTINUE, Boolean.FALSE);
			httpclient.getParams().setParameter(CoreProtocolPNames.HTTP_CONTENT_CHARSET, "utf-8");
			httpclient.getParams().setIntParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 3000);
			httpclient.getParams().setIntParameter(CoreConnectionPNames.SO_TIMEOUT, 10000);

			HttpGet httpget = new HttpGet(URL);
			HttpResponse response = httpclient.execute(httpget);
			HttpEntity entity = response.getEntity();

			String encode = null;
			if (entity != null) {
				Header header = entity.getContentType();
				if (header != null) {
					encode = header.getValue();
					int index = encode.indexOf("charset=");
					encode = index == -1 ? null : encode.substring(index + 8);
				}

				in = new BufferedInputStream(entity.getContent());
				out = new ByteArrayOutputStream();
				byte[] temp = new byte[2048];
				int size = 0;
				while ((size = in.read(temp)) != -1) {
					out.write(temp, 0, size);
				}
				byte[] content = out.toByteArray();
				if (encode == null) {
					String html_utf8 = new String(content, "utf-8");
					Pattern p = Pattern.compile("(?i)<meta.+?charset=[\"\']?(.*?)[\"\'][^/]*?/?>"); // (?i)不区分大小写
																									// [^/]除/之外的字符
					Matcher m = p.matcher(html_utf8);
					while (m.find()) {
						encode = m.group(1);
						break;
					}
				}
				String str = new String(content, encode == null ? "utf-8" : encode);
				String uri = URL.substring(0, URL.indexOf("/", 8) + 1);
				if (URL.equalsIgnoreCase("http://www.baidu.com/")
						|| URL.matches("http://www.baidu.com/index.(php|html|htm)(\\?.*)?")
						|| str.matches("(?i).*?</head>\\s*<body>\\s*</body>\\s*</html>\\s*")) {
					sb.append(defaultResult); // body内为空时显示默认提示
				} else {
					// sb.append(str.replaceAll("(?i)src=([\"\'])/",
					// "src=$1"+uri).replaceAll("(?i)(<meta.+?http-equiv=[\"\']refresh[\"\'].*?content=[\"\'].*?url=)/?(.*?[\"\'][^/]*?/?>)",
					// "$1"+uri+"$2")); //$i取第i个分组的内容，分组0是整个内容
					sb.append(str.replaceAll("(?i)<(\\\\?/?)script([\\s\\S]*?)>", "<$1noscript$2>")// script变为noscript
							.replaceAll("(?i)src=([\"\'])/", "src=$1" + uri)// script的uri变成绝对地址
							.replaceAll("(?i)(<link.*?)rel=stylesheet", "$1 rel=\"stylesheet\"")// link的rel=stylesheet变成rel="stylesheet"
							.replaceAll("(?i)(<link.*?)(href=[\"\'](\\.\\.\\/|\\/){0,2}.*?)rel=\"stylesheet\"",
									"$1 rel=\"stylesheet\" $2")// link的rel="stylesheet"统一放在href之前
							.replaceAll("(?i)(<link.*?)(rel=\"stylesheet\").*?href=[\"\'](\\/\\/)",
									"$1 rel=\"stylesheet\" href=\"http://")// link的href以//开头的链接地址加上http:
							.replaceAll("(?i)(<link.*?)(rel=\"stylesheet\").*?href=[\"\'](\\.\\.\\/|\\/){0,2}(?!http)",
									"$1 rel=\"stylesheet\" href=\"" + uri)// link的href变成绝对地址
							.replaceAll("(?i)(<img.*?)src=[\"\'](\\/\\/)", "$1 src=\"http://")// img的src以//开头的链接地址加上http:
							.replaceAll("(?i)(<img.*?)src=[\"\'](\\.\\.\\/|\\/){0,2}(?!http)", "$1src=" + '"' + uri)// img的src变成绝对地址
							.replaceAll(
									"(?i)(<meta.+?http-equiv=[\"\']refresh[\"\'].*?content=[\"\'].*?url=)/?(.*?[\"\'][^/]*?/?>)",
									"")); // 屏蔽脚本，更改文件相对路径为绝对路径，去掉跳转
				}
			}
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				if (out != null)
					out.close();
				if (in != null)
					in.close();
				if (httpclient != null)
					httpclient.getConnectionManager().shutdown();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		String result = sb.toString();
		if (result.length() == 0)
			result = defaultResult;
		return result;
	}
}